#include "ScoreManager.h"
#include "physicsComponent.h"
#include "GameObjectSystem.h"
#include "physicsComponent.h"

void ScoreManager::CreateInstance(const uint8 maxScore)
{
	if (GetSingletonPtr() == NULL)
		MV_NEW ScoreManager(maxScore);
}

ScoreManager::ScoreManager(const uint8 maxScore) 
	:m_ballId("ball1")
	,m_LeftWallId("wall2")
	,m_RightWallId("wall1")
	,m_scorePlayer1(0)
	,m_scorePlayer2(0)
	,m_maxScore(maxScore)
{	
	m_collisionSubscriber.SetSubscriber(this);
	//logScores();
}

void ScoreManager::init()
{
	// Set the ScoreManager as a subscriber for the physics component.
	Component* cmp = GameObjectSystem::GetSingleton().editComponent(PhysicsComponent::PHYSICS_COMPONENT_ID);
	if (cmp != NULL)
	{
		PhysicsComponent* physicsComponent = static_cast<PhysicsComponent*>(cmp);
		m_collisionSubscriber.Subscribe(&physicsComponent->getCollisionPublisher());
	}
}

ScoreManager::~ScoreManager()
{
}

void ScoreManager::setMaxScore(const uint8 maxScore)
{
	m_maxScore = maxScore;
}

const uint8 ScoreManager::getMaxScore() const
{
	return m_maxScore;
}

void ScoreManager::reset()
{
	m_scorePlayer1 = 0;
	m_scorePlayer2 = 0;
}

const uint8& ScoreManager::getPlayer1Score() const
{
	return m_scorePlayer1;
}

const uint8& ScoreManager::getPlayer2Score() const
{
	return m_scorePlayer2;
}

bool ScoreManager::gameOver() const
{
	return m_scorePlayer1 == m_maxScore || m_scorePlayer2 == m_maxScore;
}

bool ScoreManager::player1Wins() const
{
	return m_scorePlayer1 == m_maxScore;
}

bool ScoreManager::player2Wins() const
{
	return m_scorePlayer2 == m_maxScore;
}

void ScoreManager::fireScore(const uint8 scorePlayer1, const uint8 scorePlayer2)
{	
	ScoreData score(scorePlayer1, scorePlayer2);
	m_scorePublisher.RaiseEvent(&ScoreObserver::ScoreEvent, score);
}

Publisher<ScoreObserver>& ScoreManager::getScorePublisher()
{
	return m_scorePublisher;
}

void ScoreManager::CollisionEvent(const CollisionData& data)
{
	checkCollision(data.getObjectIdA(), data.getObjectIdB());
}

void ScoreManager::checkCollision(const ObjectId& objectAId, const ObjectId& objectBId)
{
	if (checkLeftGoal(objectAId, objectBId))
	{
		player2Scored();
		logScores();
		fireScore(m_scorePlayer1, m_scorePlayer2);
	}

	if (checkRightGoal(objectAId, objectBId))
	{
		player1Scored();
		logScores();
		fireScore(m_scorePlayer1, m_scorePlayer2);
	}
}

bool ScoreManager::checkLeftGoal(const ObjectId& objectAId, const ObjectId& objectBId) const 
{
	if ((objectAId == m_LeftWallId || objectBId == m_LeftWallId) && (objectAId == m_ballId || objectBId == m_ballId))
		return true;
	return false;
}

bool ScoreManager::checkRightGoal(const ObjectId& objectAId, const ObjectId& objectBId) const
{
	if ((objectAId == m_RightWallId || objectBId == m_RightWallId) && (objectAId == m_ballId || objectBId == m_ballId))
		return true;
	return false;
}

void ScoreManager::player1Scored()
{
	++m_scorePlayer1;
}

void ScoreManager::player2Scored()
{
	++m_scorePlayer2;
}

void ScoreManager::logScores() const
{
	DLOG(INFO) << "Scores: " << m_scorePlayer1 << " - " << m_scorePlayer2;
}